﻿// -----------------------------------------------------------------------
// <copyright file="PlaylistLogic.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Metal.Player.Playlist
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml;
    using Metal.Config;

    /// <summary>
    /// Contains the methods for Playlist form. To bind this methods on your buttons, specify in your button/menu (in xml theme file): "command="MethodName"
    /// </summary>
    public class PlaylistLogic
    {
        #region Members

        /// <summary> Stores reference to our instance </summary>
        private static PlaylistLogic instance = null;

        #endregion

        #region Constructor

        /// <summary> Gets the current instance of this class (Singleton - Thread safety) </summary>
        public static PlaylistLogic Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new PlaylistLogic();
                }

                return instance;
            }
        }

        #endregion

        #region Methods called by reflection

        /// <summary>
        /// Create new playlist
        /// </summary>
        public void NewPlaylist()
        {
            try
            {
                //// Clear ListView
                PlaylistController.ListDataSet.Tables[0].Rows.Clear();

                // Save list
                Metal.CommonForms.SaveForm saveForm = new CommonForms.SaveForm("New list", "Enter the name of the playlist");
                saveForm.ShowDialog();
                PlaylistController.CurrentListName = saveForm.FileName;

                XmlWriterSettings xmlSettings = new XmlWriterSettings();
                xmlSettings.Indent = true;
                xmlSettings.NewLineOnAttributes = true;

                XmlWriter xmlPlaylist;
                xmlPlaylist = XmlWriter.Create(Metal.Config.Paths.PlaylistsFolder + PlaylistController.CurrentListName + ".xml", xmlSettings);
                PlaylistController.ListDataSet.WriteXml(xmlPlaylist);
                xmlPlaylist.Close();

                // Refresh list of playlists
                this.RefreshListOfPlaylists();

                // Select our new list
                PlaylistController.SelectPlaylistsRow(2, PlaylistController.CurrentListName);

                // Inform user that our list is saved
                Metal.User.UserMessage.ShowInfoMessage("Playlist created!", "Now you can add media files into your playlist.");
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Open a new playlist
        /// </summary>
        public void OpenPlaylist()
        {
            try
            {
                OpenFileDialog fileBrowser = new OpenFileDialog();
                fileBrowser.InitialDirectory = Metal.Config.Paths.PlaylistsFolder;
                fileBrowser.ShowDialog();

                if (fileBrowser.FileName != string.Empty)
                {
                    // Clear ListView
                    PlaylistController.ListDataSet.Tables[0].Rows.Clear();
                    PlaylistController.ListDataSet.ReadXml(fileBrowser.FileName);
                    PlaylistController.CurrentListName = System.IO.Path.GetFileNameWithoutExtension(fileBrowser.FileName);
                    PlaylistController.SelectPlaylistsRow(2, PlaylistController.CurrentListName);

                    // Update
                    PlaylistController.CurrentView.ListDataSet = PlaylistController.ListDataSet;

                    // Since the list is changed, reset last played index
                    PlaylistController.CurrentFileIndex = 0;
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Open "Search form"
        /// </summary>
        public void SearchItem()
        {
            try
            {
                if (SearchController.View == null)
                {
                    Form searchForm = Metal.Controller.Accesibility.CreateFormInstance("Gui.Player", "Gui.Player.Playlist.SearchForm");
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Show open dialog and add to playlist
        /// </summary>
        public void AddFile()
        {
            try
            {
                OpenFileDialog fileBrowser = new OpenFileDialog();
                fileBrowser.ShowDialog();
                if (fileBrowser.FileName != string.Empty)
                {
                    this.AddFileToList(fileBrowser.FileName);
                }

                PlaylistController.SaveCurrentPlaylist();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Add folder to playlist
        /// </summary>
        public void AddFolder()
        {
            try
            {
                FolderBrowserDialog folderBrowser = new FolderBrowserDialog();

                folderBrowser.ShowDialog();
                if (folderBrowser.SelectedPath != string.Empty)
                {
                    this.AddFolderToList(folderBrowser.SelectedPath);
                }

                PlaylistController.SaveCurrentPlaylist();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Add file to playlist
        /// </summary>
        /// <param name="filePath">The file name to add</param>
        public void AddFileToList(string filePath)
        {
            try
            {
                FileInfo file = new FileInfo(filePath);
                string ext = file.Extension;

                // Filter files
                if (Core.Player.Helper.IsSupported(ext))
                {
                    PlaylistController.ListDataSet.Tables[0].Rows.Add(PlaylistController.ListDataSet.Tables[0].Rows.Count + 1, filePath, file.Name);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Add folder to playlist (include subfolders)
        /// </summary>
        /// <param name="filePath">The folder to add</param>
        public void AddFolderToList(string filePath)
        {
            try
            {
                string[] folder;
                string[] filesInFolder;

                DirectoryInfo folderInfo = new DirectoryInfo(filePath);
                ////bool isSystem = (folderInfo.Attributes == FileAttributes.Hidden && folderInfo.Attributes == FileAttributes.System);

                if (folderInfo.Exists)
                {
                    folder = Directory.GetDirectories(filePath);

                    // For each file in current folder
                    filesInFolder = Directory.GetFiles(filePath);
                    foreach (string fileName in filesInFolder)
                    {
                        FileInfo file = new FileInfo(fileName);
                        string ext = file.Extension;

                        if (Core.Player.Helper.IsSupported(ext))
                        {
                            PlaylistController.ListDataSet.Tables[0].Rows.Add(PlaylistController.ListDataSet.Tables[0].Rows.Count + 1, filePath + "\\" + file.Name, file.Name);
                        }
                    }

                    foreach (string folderName in folder)
                    {
                        // Recursively call this bullshit
                        this.AddFolderToList(folderName);
                    }

                    filePath = folderInfo.FullName;
                }

                // Update
                PlaylistController.CurrentView.ListDataSet = PlaylistController.ListDataSet;
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Clear current playlist
        /// </summary>
        public void ClearPlaylist()
        {
            try
            {
                PlaylistController.ListDataSet.Tables[0].Rows.Clear();

                PlaylistController.SaveCurrentPlaylist();

                // Update
                PlaylistController.CurrentView.ListDataSet = PlaylistController.ListDataSet;
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Remove the files from playlist that no longer exist or their have been moved
        /// </summary>
        public void RemoveInvalidFiles()
        {
            // Remove the songs that no longer exists on hard disk.
        }

        /// <summary>
        /// Show playlist settings
        /// </summary>
        public void PlaylistSettings()
        {
            try
            {
                Metal.Config.SettingsForm settings = new Config.SettingsForm(SettingsForm.ShowTab.Playlist);
                settings.ShowDialog();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Play in current order
        /// </summary>
        public void PlayInOrder()
        {
            Settings.Instance.SetValue("LastSettings.PlayRecursively", true);
            Settings.Instance.SetValue("LastSettings.PlayRandom", false);
            Settings.Instance.SetValue("LastSettings.PlaySmart", false);

            // Reload settings
            Settings.Instance.LoadSettings();
        }

        /// <summary>
        /// Play random
        /// </summary>
        public void PlayRandom()
        {
            Settings.Instance.SetValue("LastSettings.PlayRecursively", false);
            Settings.Instance.SetValue("LastSettings.PlayRandom", true);
            Settings.Instance.SetValue("LastSettings.PlaySmart", false);

            // Reload settings
            Settings.Instance.LoadSettings();
        }

        /// <summary>
        /// Play using our Intelligent Playback
        /// </summary>
        public void IntelligentPlayback()
        {
            Settings.Instance.SetValue("LastSettings.PlayRecursively", false);
            Settings.Instance.SetValue("LastSettings.PlayRandom", false);
            Settings.Instance.SetValue("LastSettings.PlaySmart", true);

            // Reload settings
            Settings.Instance.LoadSettings();
        }

        /// <summary>
        /// Play selected file
        /// </summary>
        public void PlaySelected()
        {
            try
            {
                if (PlaylistController.CurrentView.ListSelectedRow != null)
                {
                    PlaylistController.CurrentFileIndex = Convert.ToInt32(PlaylistController.CurrentView.ListSelectedRow.Index);
                    Core.Player.Playback.Instance.Open(PlaylistController.CurrentView.ListSelectedRow.Cells[1].Value.ToString());
                    Core.Player.Playback.Instance.Play();
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        public void PlayInNewInstance()
        {
            try
            {
                if (PlaylistController.CurrentView.ListSelectedRow != null)
                {
                    string fileName = "\"" + PlaylistController.CurrentView.ListSelectedRow.Cells[1].Value.ToString() + "\"";
                    System.Diagnostics.Process.Start(Application.ExecutablePath, fileName);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Show file information form (ID3 Tags and MPEG info)
        /// </summary>
        public void OpenFileInfo()
        {
            try
            {
                Metal.CommonForms.FileInfoForm fileInfoForm = new CommonForms.FileInfoForm();
                fileInfoForm.ShowDialog();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Add file to queue
        /// </summary>
        public void AddFileToQueue()
        {
            try
            {
                QueueController.AddFileToQueue(PlaylistController.CurrentView.ListSelectedRow);
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// View the files added in queue
        /// </summary>
        public void ViewQueue()
        {
            try
            {
                if (QueueController.View.IForm != null)
                {
                    if (QueueController.View.IForm.Visible == true)
                    {
                        QueueController.View.IForm.Visible = false;
                    }
                    else
                    {
                        QueueController.View.IForm.Visible = true;
                    }
                }
                else
                {
                    QueueController.View.IForm.Show();
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Copy selected file
        /// </summary>
        public void CopyFile()
        {
            try
            {
                System.Collections.Specialized.StringCollection paths = new System.Collections.Specialized.StringCollection();
                paths.Add(PlaylistController.CurrentView.ListSelectedRow.Cells[1].Value.ToString());
                Clipboard.SetFileDropList(paths);
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Open file location (folder)
        /// </summary>
        public void OpenFileLocation()
        {
            try
            {
                string path = PlaylistController.CurrentView.ListSelectedRow.Cells[1].Value.ToString();
                if (File.Exists(path))
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("explorer.exe", " /select, " + path));
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Remove selected file from playlist
        /// </summary>
        public void RemoveSelectedFromPlaylist()
        {
            try
            {
                if (Metal.User.UserMessage.ShowInfoMessage(Metal.Resources.MessageProvider.GetMessage("RES00066"), Metal.Resources.MessageProvider.GetMessage("RES00067"), true) == true)
                {
                    int selectedIndex = Convert.ToInt32(PlaylistController.CurrentView.ListSelectedRow.Cells[0].RowIndex);
                    PlaylistController.ListDataSet.Tables[0].Rows[selectedIndex].Delete();
                    PlaylistController.SaveCurrentPlaylist();

                    // Update
                    PlaylistController.CurrentView.ListDataSet = PlaylistController.ListDataSet;
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Show / hide a list of playlists
        /// </summary>
        public void ShowPlaylists()
        {
            if (PlaylistController.CurrentView.PlaylistsVisible == true)
            {
                PlaylistController.CurrentView.PlaylistsVisible = false;
                Settings.Instance.SetValue("LastSettings.ShowListOfPlaylists", false);
            }
            else
            {
                PlaylistController.CurrentView.PlaylistsVisible = true;
                Settings.Instance.SetValue("LastSettings.ShowListOfPlaylists", true);
            }
        }

        /// <summary>
        /// Rename selected playlist
        /// </summary>
        public void RenamePlaylist()
        {
            try
            {
                Metal.CommonForms.RenameForm renameForm = new CommonForms.RenameForm(PlaylistController.CurrentView.PlaylistsSelectedRow.Cells[1].Value.ToString());
                renameForm.ShowDialog();
                
                // Refresh
                this.RefreshListOfPlaylists();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Delete selected playlist
        /// </summary>
        public void DeletePlaylist()
        {
            try
            {
                if (Metal.User.UserMessage.ShowInfoMessage(Metal.Resources.MessageProvider.GetMessage("RES00058"), Metal.Resources.MessageProvider.GetMessage("RES00059"), true) == true)
                {
                    System.IO.File.Delete(PlaylistController.CurrentView.PlaylistsSelectedRow.Cells[1].Value.ToString());

                    // Refresh
                    this.RefreshListOfPlaylists();
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Refresh the list of playlists
        /// </summary>
        private void RefreshListOfPlaylists()
        {
            try
            {
                // Reload list of playlists
                PlaylistController.PlaylistsDataSet.Clear();
                string[] files = System.IO.Directory.GetFiles(Metal.Config.Paths.PlaylistsFolder);

                int nrOfLists = 0;

                foreach (string file in files)
                {
                    PlaylistController.PlaylistsDataSet.Tables[0].Rows.Add(nrOfLists, file, System.IO.Path.GetFileNameWithoutExtension(file));
                    nrOfLists++;
                }

                // Update
                PlaylistController.CurrentView.PlaylistsDataSet = PlaylistController.PlaylistsDataSet;

                PlaylistController.SelectPlaylistsRow(2, PlaylistController.CurrentListName);
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion
    }
}
